var ManageWE, NodeProperty, KeyName, WE, ShareObject;

NodeProperty = {
  a: { 
    base: [{ href: '' }, { id: '' }, { className: '' }, { title: '' }, { textContent: '' }, { target: ['_blank', '_parent', '_self', '_top']}]
  },
  table: {
    base: [{ id: '' }, { className: '' }],
    layout: [{ rows: 3 }, {columns: 3 }]
  } ,
  th: {
    base: [{ id: '' }, { className: '' }, { textContent: '' }, { rowSpan: 1 }, { colSpan: 1 }]
  },
  td: {
    base: [{ id: '' }, { className: '' }, { textContent: '' }, { rowSpan: 1 }, { colSpan: 1 }]
  },
  tr: {
    base: [{ id: '' }, { className: '' }]
  },
  ul: {
    base: [{ id: '' }, { className: '' }],
    layout: [{ child: 1 }]
  },
  li: {
    base: [{ id: '' }, { className: '' }, { textContent: '' }]
  },
  img: {
    base: [{ id: '' }, { className: '' }, { src: './2.png'}, { alt: '掌网信息'}, { width: 100 }, { height: 100 }]
  },
  form: {
    base: [{ id: '' }, { className: '' }, { method: ['GET', 'POST']}, { action: ''}]
  },
  input: {
    base: [{ id: '' }, { className: '' }, { placeholder: ''}, { name: '' },
    { type: ['text', 'url', 'number', 'search', 'tel', 'email', 'date', 'month', 'week', 'time', 'range', 'checkbox', 'file', 'radio']}]
  },
  label: {
    base: [{ id: '' }, { className: '' }, { htmlFor: '' }, { textContent: '' }]
  },
  textarea: {
    base: [{ id: '' }, { className: '' }, { rows: '' }, { cols: '' }, { placeholder: ''}]
  },
  select: {
    base: [{ id: '' }, { className: '' }],
    layout: [{ child: 1 }],
  },
  option: {
    base: [{ id: '' }, { className: '' }, { textContent: '' }, { value: '' }]
  },
  div: {
    base: [{ id: '' }, { className: '' }, { textContent: '' }]
  },
  span: {
    base: [{ id: '' }, { className: '' }, { textContent: '' }]
  },
  video: {
    base: [{ id: '' }, { className: '' }, { src: './11.mp4'}, { controls: ['true', 'false']}, { preload: ['true', 'false']}, { autoplay: ['true', 'false'] }, { width: 300 }, { height: 400 }]
  },
  source: {
    base: [{ id: '' }, { className: '' }]
  },
  audio:  {
    base: [{ id: '' }, { className: '' }, { src: ''}, { controls: ['true', 'false']}, { preload: ['true', 'false']}, { autoplay: ['true', 'false'] }, { width: '' }, { height: '' }]
  },
  canvas: {
    base: [{ id: '' }, { className: '' }, { width: '' }, { height: '' }]
  }
}

KeyName = {
  id: 'ID',
  className: 'CLASS',
  src: '链接地址',
  width: '宽',
  height: '高',
  controls: '显示控制',
  preload: '提前加载',
  autoplay: '自动播放',
  textContent: '文本内容',
  type: '类型',
  rows: '行数',
  columns: '列数',
  rowSpan: '跨行',
  colSpan: '跨列',
  child: '子元素',
  method: '方式',
  action: '提交地址',
  href: '链接地址',
  children: '子数量',
  title: '标题',
  placeholder: '占位符',
  htmlFor: '对应ID',
  cols: '列数',
  name: '控件名',
  target: '打开位置',
  value: '值',
  alt: '占位字'
}


/**
 * nodeName 代表对象元素的类型
 * element 代表对象元素
 * parent 表示插入了那个WE对象下面
 * depth 表示该对象的深度
 */
WE = function (nodeName) {
  this.nodeName = nodeName;
  this.element = document.createElement(nodeName);
  this.parent = undefined;
  this.depth = 0;
}

WE.prototype = {

  // 将propertyObject的属性全部赋予到该对象的元素上
  attachBaseProperty: function (propertyObject) {
    var keyArray = Object.keys(propertyObject);
    var that = this;
    keyArray.forEach(function (key) {
      that.element[key] = propertyObject[key];
    });
    

    return this;
  },

  attachLayoutProperty: function (propertyObject) {
    // 呈现元素只有部分函数有，将函数移除出去
    ShareObject.showOut(this.element, propertyObject);

    return this;
  },

  //  将元素添加到父元素的末尾
  create: function (parentElement) {
    parentElement.appendChild(this.element);

    ManageWE.add(this, ManageWE.length);

    this.depth = 1;
    this.parent = null;

    return this;
  },

  // 将元素添加到we对象的元素属性中
  createByWe: function (we) {
    we.element.appendChild(this.element);
    this.parent = we;

    ManageWE.add(this, ManageWE.indexOf(we) + ManageWE.getLength(we));

    this.depth = we.depth + 1;

    return this;
  },

  // 将对象组添加到we对象下
   /*
    将字符串解析为对象数组
    >：表示是前一个元素的子元素
    <: 表示前一个元素的父元素同级
    +：表示前一个元素的祖父元素同级
    @：表示前一个元素的上三代元素同级
    #：表示前一个元素的上四代元素同级
    &：表示前一个元素的上五代元素同级
  */ 
  createWeArray: function (objectArray) {
    var activeWe = this;
    var firstWe;

    objectArray.forEach(function (object, index) {
      var we = new WE(object.nodeName);
      switch (object.location) {
        case 't':
        case '>':
          we.createByWe(activeWe);
          break;
        case '+':
          we.createByWe(activeWe.parent);
          break;
        case '<':
          we.createByWe(activeWe.parent.parent);
          break;
        case '@':
          we.createByWe(activeWe.parent.parent.parent);
          break;
        case '#':
          we.createByWe(activeWe.parent.parent.parent.parent);
          break;
        case '&':
          we.createByWe(activeWe.parent.parent.parent.parent.parent);
          break;
      }
      we.element.className = object.className;

      activeWe = we;
      if (index === 0) {
        firstWe = we;
      }
    });

    return firstWe;
  },

  remove: function (parentElement) {
    parentElement.removeChild(this.element);

    ManageWE.removeAll(this);

    return this;
  },

  //  根据nodeName, 以及该元素的属性，返回对应的html
  displayPropertyHtml: function () {
    var strObject = NodeProperty[this.nodeName];

    // 提取出base属性的对象组
    var baseArray = strObject.base;
    var baseHtml = '<div class="base-attribute"><h2>元素属性</h2><ul>';
    var that = this;

    // 遍历数组里面的每个对象，如果是‘’，用text类型的input，如果数字，则用number的input，如果是数组，则用select的类型
    // 并且元素的值作为输入框的值
    baseArray.forEach(function (base) {
      var key, value, strHtml;

      //只有一个属性，将key设为该键值
      for (var i in base) {
        key = i;
      }

      // 针对不同的值， 显示不同的html;
      if (typeof base[key] === 'string') {
        value = that.element[key] || base[key];
        if (key == 'src') {
          value = that.element.getAttribute('src') || base[key];
        }
        if (key !== 'textContent') {
          strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><input id="' + key + '" type="text" placeholder="请输入' + KeyName[key] + '" value="' + value + '"></li>';
        }
        else {
          if (!ManageWE.hasChild(that)) {
            strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><textarea id="' + key + '"  placeholder="请输入' + KeyName[key] + '">' + that.element.textContent + '</textarea></li>';
          }
          else {
            strHtml = '';
          }
        }

        if (key == 'src' && that.link === false) {
          strHtml = '';
        }
      } 
      else if (typeof base[key] === 'number') {
        value = that.element[key] || base[key];
        strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><input id="' + key + '" type="number" placeholder="请输入' + KeyName[key] + '" value="' + value + '"></li>';
      }
      else {
        var temp = '<option value="#">#</option>';

        var tempArray = base[key].map(function (tempValue) {
          return temp.replace(/#/g, tempValue);
        }).join("");

        strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><select id="' + key + '">' + tempArray + '</select></li>';
      }
      baseHtml += strHtml;
    });

    baseHtml += '</ul>' + '<button data-change="base">确认更改</button></div>';
    var layoutHtml = '';

    if (strObject.layout) {
      // 提取layout属性的对象组
      layoutHtml += '<div class="layout-attribute"><h2>呈现属性</h2><ul>';
      var layoutArray = strObject.layout;

      // 方法与上述类型
      layoutArray.forEach(function (layout) {
        var key, value, strHtml;

        for (var i in layout) {
          key = i;
        }
        
        // 针对不同的值， 显示不同的html;
        if (typeof layout[key] === 'string') {
          value = layout[key];
          strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><input id="' + key + '" type="text" placeholder="请输入' + KeyName[key] + '" value="' + value + '"></li>';
        } 
        else if (typeof layout[key] === 'number') {
          value = layout[key];
          strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><input id="' + key + '" type="number" placeholder="请输入' + KeyName[key] + '" value="' + value + '"></li>';
        }
        else {
          var temp = '<option value="#">#</option>';
          var tempArray = layout[key].map(function (tempValue) {
            return temp.replace(/#/g, tempValue);
          }).join("");
          
          strHtml = '<li>' + KeyName[key] + ': </li>' + '<li><select id="' + key + '">' + tempArray + '</select></li>';
        }
        layoutHtml += strHtml;
      });

      layoutHtml += '</ul>' + '<button data-change="layout">确认更改</button></div>';
    }
    
    return baseHtml + layoutHtml;
  },

  showChildElement: function () {},

};

// 这个类数组对象是用来管理we元素,排序的方式按深度优先
ManageWE = {
  length: 0,

  // 添加we类型的方法
  add: function (we, i) {

    if (typeof i === 'undefined') {
      Array.prototype.unshift.call(this, we);
    }
    else {
      Array.prototype.splice.call(this, i, 0, we);
    }
  },

  // 移除
  remove: function (we) {
    var index = Array.prototype.indexOf.call(this, we);
    Array.prototype.splice.call(this, index, 1);
  },

  // 获得索引值
  indexOf: function (we) {
    var index = Array.prototype.indexOf.call(this, we);
    return index;
  },

  // 用子元素来查找we元素的索引值
  getIndexByElement: function (element) {
    var len = this.length;
    for (var i = 0; i < len; i++) {
      if (element === this[i].element) {
        return i;
      }
    }
  },

  // 删除we元素以及它对应的后台元素
  removeAll: function (we) {
    var length = this.getLength(we);
    var index = Array.prototype.indexOf.call(this, we);;

    Array.prototype.splice.call(this, index, length);
  },

  // 获取该元素的包括子元素的长度
  getLength: function (we) {
    var index = Array.prototype.indexOf.call(this, we);
    var length = 1;
    
    // 后面元素若是该元素的后代元素，那么length加1，直到查到不是的跳出
    for (var i = index + 1; i < this.length; i++) {
      if (ShareObject.isInherit(we, this[i])) {
        length++
      }
      else {
        break;
      }
    }

    return length;
  },

  // 通过element找到WE这个对象
  getWeByElement: function (element) {
    for (var i = 0; i < this.length; i++) {
      if (element === this[i].element) {
        break;
      }
    }

    return this[i];
  },

  // 将we数组转化为树结构的html
  parseAllHTML: function () {
    var weArray = Array.prototype.slice.call(this, 0, this.length);
    var ulliEnd = 0;
    var ulliHTML = weArray.map(function (we, index, array) {
      if (index == 0) {
        return '<ul><li data-content="' + ManageWE.indexOf(we) + '"><span>x</span>' + we.nodeName + '</li>';
      }
      else {
        if (we.depth === array[index - 1].depth) {
          return '<li data-content="' + ManageWE.indexOf(we) + '"><span>x</span>' + we.nodeName + '</li>';
        }
        else if (we.depth > array[index - 1].depth) {
          ulliEnd++;
          return '<li><i data-active="true"></i><ul><li data-content="' + ManageWE.indexOf(we) + '"><span>x</span>' + we.nodeName + '</li>';
        }
        else if (we.depth < array[index - 1].depth) {
          var length = array[index - 1].depth - we.depth;
          var ullistr = '';
          
          for (var j = 0; j < length; j++) {
            ullistr += '</ul></li>';
          }

          ulliEnd -= length;
          return ullistr + '<li data-content="' + ManageWE.indexOf(we) + '"><span>x</span>' + we.nodeName + '</li>';
        }
      }
    }).join('');

    for (var i = 0; i < ulliEnd; i++) {
      ulliHTML += '</ul></li>';
    }

    return ulliHTML += '</ul>';
  },

  //  判断we是否有子元素
  hasChild: function (we) {
    var index = Array.prototype.indexOf.call(this, we);
    var nextWe = this[index + 1];
    try {
      return nextWe.parent == we ? true : false;
    }
    catch (ex) {
      return false;
    }
  },

  //  获得指定we对象下面拥有content的we数组
  getContentArray: function (we) {
    var index = Array.prototype.indexOf.call(this, we);
    var length = this.getLength(we);
    var array = [];

    for (var i = index, len = index + length; i < len; i++) {
      if (!this.hasChild(this[i]) && ShareObject.hasTextContent(this[i].element)) {
        array.push(this[i]);
      }
    }

    return array;
  },

  getAllContentArray: function () {
    var array = [];

    for (var i = 0, len = this.length; i < len; i++) {
      if (!this.hasChild(this[i]) && ShareObject.hasTextContent(this[i].element)) {
        array.push(this[i]);
      }
    }

    return array;
  }

};

ShareObject = {

  // 判断we对象是否有textContent输出
  hasTextContent: function (element) {
    var nodeName = element.nodeName.toLowerCase();
    return (nodeName == 'a') || (nodeName == 'th') || (nodeName == 'td')  || (nodeName == 'li')  || (nodeName == 'label') ||
         (nodeName == 'option') || (nodeName == 'div') || (nodeName == 'span');
  },

  // 将表单里面输出，表单对象
  getInputObject: function (element) {
    var inputArray = element.querySelectorAll('input, select, textarea');
    var dataObj = {};

    [].forEach.call(inputArray, function (input) {
      if (input.value === 'false') {
        dataObj[input.id] = false;
      }
      else if (input.value === 'true'){
        dataObj[input.id] = true;
      }
      else {
        dataObj[input.id] = input.value;
      }
    });

    return dataObj;
  },

  // 将呈现对象赋予到该对象上
  showOut: function (element, propertyObject) {

    switch (element.nodeName.toLowerCase()) {
      case 'select':
        var num = propertyObject.child;
        // 先移除select下面的是所有元素，然后根据数量来添加元素
        var selectWE = ManageWE.getWeByElement(element);
        var selectChild = element.children;

        for (var i = selectChild.length - 1; i > -1; i--) {
          var optionWE = ManageWE.getWeByElement(selectChild[i]);
          optionWE.remove(selectWE.element);
        }

        for (var i = 0; i < num; i++) {
          var optionWE = new WE('option');
          optionWE.element.textContent = 'option' + i;
          optionWE.createByWe(selectWE);
        }

        break;
      case 'table': 
        // 先移除table下面的所有元素，然后再根据列和行数来添加元素

        var tableWE = ManageWE.getWeByElement(element);
        var tableChild = element.children;

        // 遍历所有的tr，并且移除他们
        for (var i = tableChild.length - 1; i > -1; i--) {
          var trWE = ManageWE.getWeByElement(tableChild[i]);
          trWE.remove(tableWE.element);
        }

        // 读取行数和列数
        var row = propertyObject.rows;
        var col = propertyObject.columns;

        for (var i = 0; i < row; i++) {
          var newTrWE = new WE('tr');
          newTrWE.createByWe(tableWE);
          
          for (var j = 0; j < col; j++) {

            if (i === 0) {
              var thWE = new WE('th');
              thWE.element.textContent = 'th'+ i + j;
              thWE.createByWe(newTrWE);
            }
            else {
              var tdWE = new WE('td');
              tdWE.element.textContent = 'td' + i + j;
              tdWE.createByWe(newTrWE);
            }
          }

        }

        break;
      case 'ul': 

      // 先移除ul下面的所有元素，然后再根据数量来添加元素
        var ulWE = ManageWE.getWeByElement(element);
        var ulChild = element.children;

        //遍历所有的li，并且移除他们
        for (var i = ulChild.length - 1; i > -1; i--) {
          var liWE = ManageWE.getWeByElement(ulChild[i]);
          liWE.remove(ulWE.element);
        }

        // 读取列数
        var num = propertyObject.child;
        for (var i = 0; i < num; i++) {
          var liWE = new WE('li');
          liWE.element.textContent = 'li' + i;
          liWE.createByWe(ulWE);
        }

        break;
    }
  },

  // 判断两个we对象是不是有遗传关系, w1是前辈， w2是晚辈
  isInherit: function (w1, w2) {
    try {
      var parent = w2.parent;
      
      // 如果w2的父元素是w1，那么返回true，如果不是继续往上走，往上走碰到null，捕获异常，返回false
      while (w1 !== parent) {
        parent = parent.parent;
      }
    }
    catch (ex) {
      return false;
    }

    return true;
  },

  /*
    将字符串解析为对象数组
    >：表示是前一个元素的子元素
    <: 表示前一个元素的父元素同级
    +：表示前一个元素的祖父元素同级
    @：表示前一个元素的上三代元素同级
    #：表示前一个元素的上四代元素同级
    &：表示前一个元素的上五代元素同级
  */ 
  stringToObj: function (multiStr) {
    var strArray = multiStr.split(/[><+@#&]/g);
    var i = 0;
    var o = [];

    strArray.forEach(function (str, index) {
      var length = str.length;
      var object = {};
      var strArray;

      strArray = str.split(/\./g);
      object.nodeName = strArray[0];
      object.className = strArray.slice(1).join(' ');
      
      if (index === 0) {
        object.location = 't';
        i += length;
      }
      else {
        var key = multiStr.slice(i, i + 1);
        object.location = key;
        i += length + 1;
      }
      o.push(object);
    });

    return o;
  },

  // 将对象组添加到元素对象下
  createWeArrayByElement: function (objectArray, element) {
    var activeWe;
    var firstWe;
    
    objectArray.forEach(function (object, index) {
      var we = new WE(object.nodeName);
      if (object.className) {
        we.element.className = object.className;
      }

      switch (object.location) {
        case 't':
          we.create(element);
          break;
        case '>':
          we.createByWe(activeWe);
          break;
        case '+':
          we.createByWe(activeWe.parent);
          break;
        case '<':
          if (activeWe.parent.parent !== null) {
            we.createByWe(activeWe.parent.parent);
          }
          else {
            we.create(element);
          }
          break;
        case '@':
          if (activeWe.parent.parent.parent !== null) {
            we.createByWe(activeWe.parent.parent.parent);
          }
          else {
            we.create(element);
          }
          break;
        case '#':
          if (activeWe.parent.parent.parent.parent !== null) {
            we.createByWe(activeWe.parent.parent.parent.parent);
          }
          else {
            we.create(element);
          }
          break;
        case '&':
          if (activeWe.parent.parent.parent.parent.parent !== null) {
            we.createByWe(activeWe.parent.parent.parent.parent.parent);
          }
          else {
            we.create(element);
          }
          break;

      }

      activeWe = we;
      if (index === 0) {
        firstWe = we;
      }
    });

    return firstWe;
  },

  // 将对象组转为成dom对象
  createElementByArray: function (objectArray) {
    var fragment = document.createDocumentFragment();
    var activeElement;

    objectArray.forEach(function (object, index) {
      var element = document.createElement(object.nodeName);
      if (object.className) {
        element.className = object.className;
      }

      switch (object.location) {
        case 't':
          fragment.appendChild(element);
          break;
        case '>':
          activeElement.appendChild(element);
          break;
        case '+':
          activeElement.parentNode.appendChild(element);
          break;
        case '<':
          if (activeElement.parentNode.parentNode !== null) {
            activeElement.parentNode.parentNode.appendChild(element);
          }
          else {
            fragment.appendChild(element);
          }
          break;
        case '@':
          if (activeElement.parentNode.parentNode.parentNode !== null) {
            activeElement.parentNode.parentNode.parentNode.appendChild(element);
          }
          else {
            fragment.appendChild(element);
          }
          break;
        case '#':
          if (activeElement.parentNode.parentNode.parentNode.parentNode !== null) {
            activeElement.parentNode.parentNode.parentNode.parentNode.appendChild(element);
          }
          else {
            fragment.appendChild(element);
          }
          break;
        case '&':
          if (activeElement.parentNode.parentNode.parentNode.parentNode.parentNode !== null) {
            activeElement.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(element);
          }
          else {
            fragment.appendChild(element);
          }
          break;

      }
      activeElement = element;
    });

    return fragment;
  }

}